package com.tools.cleanmaster.cpucool;

import android.app.ActivityManager;
import android.content.Context;
import android.os.Handler;

import com.tools.acceleratecore.AccelerateCoreFactory;
import com.tools.acceleratecore.logic.accelerate.temperature.intf.ITemperatureMgr;
import com.tools.cleanmaster.CleanApplication;
import com.tools.cleanmaster.R;
import com.tools.cleanmaster.common.thread.ThreadPool;
import com.tools.cleanmaster.cpucool.util.PhoneAccelerateHelper;
import com.tools.cleanmaster.store.CpuCoolSharedPrefManager;
import com.tools.cleanmaster.taskmain.AppTaskUtils;
import com.tools.cleanmaster.taskmain.ProcessItem;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 * Created by wangguotao on 15/8/28.
 */
public class CpuCoolManager implements ManagerInterface, CpuCoolInterface {
    public static final long MINUTE_MS = 1000l * 60;
    public static CpuCoolManager mInstance;

    private ArrayList<WeakReference<GetCpuTempListener>> mListeners;
    private ITemperatureMgr mTempNativeMgr;
    private double mLastTemp = 0f;
    private double mLastOptimizeTemp = 0f;
    private boolean isRunning = false;
    private Handler mMainHandler;
    private MakeCpuCoolRunnable mRunnable;
    private GetCpuTempRunnable mGetRunnable;

    // 是否需要更新温度的标志
    public boolean mNeedUpdateTem;

    public static CpuCoolManager getInstance() {
        if (mInstance == null) {
            synchronized (CpuCoolManager.class) {
                if (mInstance == null) {
                    mInstance = new CpuCoolManager();
                }
            }
        }
        return mInstance;
    }

    /**
     * 杀死正在运行的应用
     */
    private class MakeCpuCoolRunnable implements Runnable {
        private List<ProcessItem> mKillItems = new ArrayList<ProcessItem>(1);

        public void setProcessList(List<ProcessItem> items) {
            synchronized (mKillItems) {
                mKillItems.clear();
                if (items != null) {
                    mKillItems.addAll(items);
                }
            }
        }

        private List<ProcessItem> getProcessItems() {
            List<ProcessItem> items = new ArrayList<ProcessItem>();
            synchronized (mKillItems) {
                items.addAll(mKillItems);
            }
            return items;
        }

        @Override
        public void run() {
            Context ctx = CleanApplication.getInstance().getApplicationContext();
            PhoneAccelerateHelper.executeAccelerateTask(ctx, getProcessItems());
            mMainHandler.post(new Runnable() {
                @Override
                public void run() {
                    killProcessDone();
                }
            });
            synchronized (mKillItems) {
                mKillItems.clear();
            }
        }
    }

    /**
     * 获取CPU温度
     */
    private class GetCpuTempRunnable implements Runnable {
        private boolean mIsNeedProcess;
        private boolean mIsUpdate;

        public GetCpuTempRunnable(boolean isNeedProcess) {
            mIsNeedProcess = isNeedProcess;
        }

        public void setIsNeedProcess(boolean isNeedProcess) {
            mIsNeedProcess = isNeedProcess;
        }

        public void setIsNeedUpdate(boolean isUpdate) {
            mIsUpdate = isUpdate;
        }

        @Override
        public void run() {
            final CpuTempInfo info = startGetCpuTempSync(mIsNeedProcess, mIsUpdate);
            mMainHandler.post(new Runnable() {
                @Override
                public void run() {
                    synchronized (mListeners) {
                        Iterator<WeakReference<GetCpuTempListener>> iter = mListeners.iterator();
                        GetCpuTempListener lis;

                        while (iter.hasNext()) {
                            lis = iter.next().get();
                            if (lis != null) {
                                lis.onGetCpuTempDone(info);
                            }
                        }
                        isRunning = false;
                    }
                }
            });
        }
    }


    @Override
    public void addListener(GetCpuTempListener listener) {
        synchronized (mListeners) {
            mListeners.add(new WeakReference<GetCpuTempListener>(listener));
        }
    }

    @Override
    public void removeListener(GetCpuTempListener listener) {
        synchronized (mListeners) {
            Iterator<WeakReference<GetCpuTempListener>> iter = mListeners.iterator();
            GetCpuTempListener lis;
            while (iter.hasNext()) {
                lis = iter.next().get();
                if (lis == null || lis == listener) {
                    iter.remove();
                }
            }
        }
    }

    /**
     * 同步获取CPU温度
     *
     * @param haveIcon
     * @param isUpdate
     * @return
     */
    @Override
    public CpuTempInfo startGetCpuTempSync(boolean haveIcon, boolean isUpdate) {
        boolean isProtect = isInProtectTime();
        if (isProtect) {
            mLastTemp = CpuCoolSharedPrefManager.getCpuCoolLastTemp();
            mLastOptimizeTemp = CpuCoolSharedPrefManager.getCpuCoolLastTempDrop();
        } else if (isUpdate) {
            mTempNativeMgr.startScanTemperatureSyn();
            mLastOptimizeTemp = mTempNativeMgr.getOptimizeTemperature();
            mLastTemp = mTempNativeMgr.getTemperature();
        }
        List<ProcessItem> icons;
        if (haveIcon) {
            icons = getRunningApp();
        } else {
            icons = Collections.emptyList();
        }
        return new CpuTempInfo(mLastTemp, mLastOptimizeTemp, isProtect, icons);
    }

    @Override
    public void startGetCpuTempAsync(boolean haveIcon, boolean isUpdate) {
        if (isRunning == false) {
            isRunning = true;
            mGetRunnable.setIsNeedProcess(haveIcon);
            mGetRunnable.setIsNeedUpdate(isUpdate);
            ThreadPool.runOnPool(mGetRunnable);
        }
    }

    @Override
    public void startCpuCoolSync(List<ProcessItem> items) {
        Context ctx = CleanApplication.getInstance().getApplicationContext();
        PhoneAccelerateHelper.executeAccelerateTask(ctx, items);
    }

    @Override
    public void startCpuCoolAsync(List<ProcessItem> items) {
        mRunnable.setProcessList(items);
        ThreadPool.runOnPool(mRunnable);
    }

    @Override
    public boolean isInProtectTime() {
        return (System.currentTimeMillis() > CpuCoolSharedPrefManager.getCpuCoolLastTime()) &&
                (System.currentTimeMillis() < CpuCoolSharedPrefManager.getCpuCoolLastTime() + MINUTE_MS * 5);
    }

    @Override
    public int getLastOptimizerTemp() {
        return (int) mLastOptimizeTemp;
    }

    @Override
    public int getLastTemp() {
        return (int) (mLastTemp + mLastOptimizeTemp);
    }


    @Override
    public int getCpuTempState() {
        int cpuState;
        long lastTime = CpuCoolSharedPrefManager.getCpuCoolLastTime();
        if (lastTime == 0) {
            cpuState = CPU_TEMP_STATE_FIRST;
        } else if (isInProtectTime()) {
            cpuState = CPU_TEMP_STATE_PROTECT;
        } else {
            cpuState = CPU_TEMP_STATE_NORMAL;
        }
        return cpuState;
    }

    @Override
    public String getCpuCoolLastTime() {
        Context ctx = CleanApplication.getInstance().getApplicationContext();
        String timeUnit = new String();
        String offSetTimeString = new String();
        long lastTime = CpuCoolSharedPrefManager.getCpuCoolLastTime();
        long offsetTime = System.currentTimeMillis() - lastTime;
        String lastTimeStr;
        if (offsetTime <= 0) {
            timeUnit = ctx.getResources().getString(R.string.acc_list_header_time_just);
            offSetTimeString = timeUnit;
            lastTimeStr = ctx.getResources().getString(R.string.acc_list_header_cpu_temp_last_cool) + offSetTimeString;
        } else if (offsetTime < (60 * 60 * 1000L)) {
            timeUnit = ctx.getResources().getString(R.string.acc_list_header_time_min);
            offSetTimeString = (offsetTime / (60 * 1000L)) + timeUnit;
            lastTimeStr = ctx.getResources().getString(R.string.acc_list_header_cpu_temp_last_cool_time, offSetTimeString);
        } else if (offsetTime < (24 * 60 * 60 * 1000L)) {
            timeUnit = ctx.getResources().getString(R.string.acc_list_header_time_hour);
            offSetTimeString = (offsetTime / (60 * 60 * 1000L)) + timeUnit;
            lastTimeStr = ctx.getResources().getString(R.string.acc_list_header_cpu_temp_last_cool_time, offSetTimeString);
        } else if (offsetTime < (30 * 24 * 60 * 60 * 1000L)) {
            timeUnit = ctx.getResources().getString(R.string.acc_list_header_time_day);
            offSetTimeString = (offsetTime / (24 * 60 * 60 * 1000L)) + timeUnit;
            lastTimeStr = ctx.getResources().getString(R.string.acc_list_header_cpu_temp_last_cool_time, offSetTimeString);
        } else if (offsetTime < (12 * 30 * 24 * 60 * 60 * 1000L)) {
            timeUnit = ctx.getResources().getString(R.string.acc_list_header_time_mon);
            offSetTimeString = (offsetTime / (30 * 24 * 60 * 60 * 1000L)) + timeUnit;
            lastTimeStr = ctx.getResources().getString(R.string.acc_list_header_cpu_temp_last_cool_time, offSetTimeString);
        } else {
            timeUnit = ctx.getResources().getString(R.string.acc_list_header_time_year);
            offSetTimeString = (offsetTime / (12 * 30 * 24 * 60 * 60 * 1000L)) + timeUnit;
            lastTimeStr = ctx.getResources().getString(R.string.acc_list_header_cpu_temp_last_cool_time, offSetTimeString);
        }
        return lastTimeStr;
    }


    @Override
    public void initManager() {
        mTempNativeMgr = (ITemperatureMgr) AccelerateCoreFactory
                .getInstance().createInstance(ITemperatureMgr.class);
        Context ctx = CleanApplication.getInstance().getApplicationContext();
        mMainHandler = new Handler(ctx.getMainLooper());
        mRunnable = new MakeCpuCoolRunnable();
        mGetRunnable = new GetCpuTempRunnable(true);
        mListeners = new ArrayList<WeakReference<GetCpuTempListener>>();
        mNeedUpdateTem = true;
    }

    @Override
    public void stopManager() {

    }

    /**
     * 设置是否需要更新CPU的温度<br>
     *
     * @param needUpdate
     */
    public void setNeedUpdateTem(boolean needUpdate) {
        mNeedUpdateTem = needUpdate;
    }

    /**
     * 是否需要更新CPU的温度<br>
     *
     * @return mNeedUpdateTem
     */
    public boolean getNeedUpdateTem() {
        return mNeedUpdateTem;
    }

    /**
     * 设置CPU降温后应用的保护时间<br>
     *
     * @param appsProtect
     */
    public void setAppsProtect(final List<ProcessItem> appsProtect) {
        PhoneAccelerateHelper.setAppsProtect(appsProtect);
    }

    /*
     * runnable 调用killProcessDone
     */
    private void killProcessDone() {
        synchronized (mListeners) {
            Iterator<WeakReference<GetCpuTempListener>> iter = mListeners.iterator();
            GetCpuTempListener lis;
            while (iter.hasNext()) {
                lis = iter.next().get();
                if (lis != null) {
                    lis.onMakeCpuCoolDone(mLastOptimizeTemp, mLastTemp);
                }
            }
        }
    }

    /*
     * 获取应用的icon列表
     */
    private ArrayList<ProcessItem> getRunningApp() {
        final Context context = CleanApplication.getInstance().getApplicationContext();
        final ActivityManager acManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        HashMap<String, ProcessItem> processMap = new HashMap<String, ProcessItem>();
        AppTaskUtils.getRunningTaskList(context, acManager, processMap, true, false, null);
        ArrayList<ProcessItem> items = new ArrayList<ProcessItem>(processMap.values());
        Iterator<ProcessItem> iter = items.iterator();
        ProcessItem item;
        while (iter.hasNext()) {
            item = iter.next();
            if (item.checked == false) {
                iter.remove();
            }
        }
        return items;
    }
}
